import 'dart:typed_data';

import 'package:binary/binary.dart';
import 'package:inmotion_protocol/base/vehicle_data.dart';
import 'package:inmotion_protocol/common/compact.dart';
import 'package:inmotion_protocol/common/mode.dart';
import 'package:inmotion_protocol/common/product_model.dart';
import 'package:inmotion_protocol/common/product_version.dart';
import 'package:inmotion_protocol/lorin/bean/base/vehicle_real_time_info.dart';
import 'package:inmotion_protocol/lorin/bean/euc/euc_real_time_data.dart';
import 'package:inmotion_protocol/util/byte_util.dart';

class AllV6RealTimeData extends AllRealTimeData<V6RealTimeInfo, V6RealTimeState, V6RealTimeError> {
  AllV6RealTimeData(V6RealTimeInfo realTimeInfo, V6RealTimeState realTimeState, V6RealTimeError realTimeError) : super(realTimeInfo, realTimeState, realTimeError);
}

class V6VehicleSynthesizeRealTimeInfo extends VehicleSynthesizeRealTimeInfo<CommonVehicleRealTimeInfo, V6RealTimeState, V6RealTimeError> {
  V6VehicleSynthesizeRealTimeInfo(CommonVehicleRealTimeInfo commonVehicleRealTimeInfo, V6RealTimeState realTimeState, V6RealTimeError realTimeError) : super(commonVehicleRealTimeInfo, realTimeState, realTimeError);
}

/// 实时信息
class V6RealTimeInfo extends EucRealTimeInfo {
  Uint8 lowLampBrightness = Uint8.zero;
  Uint8 highLampBrightness = Uint8.zero;

  V6RealTimeInfo(super.model, super.version);

  @override
  void initCompact() {
    compact = _DefaultV6RealTimeInfo();
  }

  @override
  String toString() {
    return 'V6RealTimeInfo{${super.toString()}, lowLampBrightness: $lowLampBrightness, mosTemp: $mosTemp, boardTemp: $boardTemp}';
  }
}

class _DefaultV6RealTimeInfo extends Compact<V6RealTimeInfo> {
  @override
  void fromBytes(V6RealTimeInfo output, Uint8ClampedList bytes, int offset) {
    if (bytes.length < offset + output.length()) {
      return;
    }
    output.voltage = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.current = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.speed = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.torque = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.outputRate = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.batteryOutputPower = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.motorOutputPower = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 4;
    output.pitchAngle = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.pitchAimAngle = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.rollAngle = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.mileage = ByteUtil.bytes2Uint16Le(bytes, offset);

    offset += 2;
    output.batteryLevel = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.batteryLevelForRide = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.estimatedTotalMileage = ByteUtil.bytes2Uint16Le(bytes, offset);
    output.remainderRange = Uint16(((output.batteryLevelForRide.value / 10000) * output.estimatedTotalMileage.value).toInt());
    offset += 2;
    output.dynamicSpeedLimit = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.dynamicCurrentLimit = ByteUtil.bytes2Int16Le(bytes, offset);
    
    offset += 8;
    output.mosTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset += 1;
    output.motorTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset += 1;
    output.batteryTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset += 1;
    output.boardTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset += 1;
    output.cpuTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset += 1;
    output.imuTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset += 1;
    output.lampTemp = ByteUtil.toInt16(ByteUtil.toInt8Int(bytes[offset]) + 80);
    offset += 1;
    output.brightness = ByteUtil.bytes2Uint8Le(bytes, offset);
    offset += 1;
    output.lowLampBrightness = ByteUtil.bytes2Uint8Le(bytes, offset);
    offset += 1;
    output.highLampBrightness = ByteUtil.bytes2Uint8Le(bytes, offset);
  }

  @override
  int length() {
    return 54;
  }
}

/// 实时状态
class V6RealTimeState extends EucRealTimeState {
  V6RealTimeState(ProductModel model, VersionWrapper version) : super(model, version);

  @override
  void initCompact() {
    compact = _DefaultV6RealTimeState();
  }
}

class _DefaultV6RealTimeState extends Compact<V6RealTimeState> {
  @override
  void fromBytes(V6RealTimeState output, Uint8ClampedList bytes, int offset) {
    // 3bit
    output.pcModeValue = ByteUtil.toUint32(ByteUtil.bitValue(bytes[offset], 0, 3).value);
    if (output.pcModeValue.value == 0) {
      output.pcMode = Mode.idle;
    } else if (output.pcModeValue.value == 1) {
      output.pcMode = Mode.working;
    } else if (output.pcModeValue.value == 2) {
      output.pcMode = Mode.sleep;
    } else if (output.pcModeValue.value == 3) {
      output.pcMode = Mode.locked;
    }
    output.lockState = output.pcMode == Mode.locked ? Uint4(1) : Uint4.zero;
    output.mcMode = ByteUtil.bitValue(bytes[offset], 3, 3);
    output.motorState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.chargeState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;

    output.headlightState = ByteUtil.bitValue(bytes[offset], 0, 1);

    // 跳过 1bit

    output.liftedState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.tailLightState = ByteUtil.bitValue(bytes[offset], 3, 2);
    output.dfuState = ByteUtil.bitValue(bytes[offset], 5, 2);
  }

  @override
  int length() {
    return 4;
  }
}

/// 实时故障和警告
class V6RealTimeError extends EucRealTimeError {
  V6RealTimeError(ProductModel model, VersionWrapper version) : super(model, version);

  @override
  void initCompact() {
    compact = _DefaultV6RealTimeError();
  }

  @override
  String toString() {
    return 'V6RealTimeError{ ${super.toString()}, riskBehaviourState: $riskBehaviourState}';
  }
}

class _DefaultV6RealTimeError<V6RealTimeError> extends _DefaultV6RealTimeErrorImpl {}

class _DefaultV6RealTimeErrorImpl<T extends V6RealTimeError> extends Compact<T> {
  @override
  void fromBytes(T output, Uint8ClampedList bytes, int offset) {
    output.originalValue = ByteUtil.bytes2Int32Le(bytes, offset);

    output.iPhaseSensorState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.iBusSensorState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.motorHallState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.batteryState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.imuSensorState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.controllerCom1State = ByteUtil.bitValue(bytes[offset], 5, 1);
    output.controllerCom2State = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.bleCom1State = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;
    output.bleCom2State = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.mosTempSensorState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.motorTempSensorState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.batteryTempSensorState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.boardTempSensorState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.fanState = ByteUtil.bitValue(bytes[offset], 5, 1);
    output.rtcState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.externalRomState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;
    output.vBusSensorState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.vBatterySensorState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.canNotPowerOffState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.canNotChargeState = ByteUtil.bitValue(bytes[offset], 3, 1);
    // 剩余4bit保留
    // 剩余1byte保留
    offset++;

    offset++;

    // 警告
    output.underVoltageState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.overVoltageState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.overBusCurrentState = ByteUtil.bitValue(bytes[offset], 2, 2);
    output.lowBatteryState = ByteUtil.bitValue(bytes[offset], 4, 2);
    output.overMosTempState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.overMotorTempState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;
    output.overBatteryTempState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.overBoardTempState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.overSpeedState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.outputSaturationState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.motorSpinState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.motorBlockState = ByteUtil.bitValue(bytes[offset], 5, 1);
    output.postureState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.riskBehaviourState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;

    output.motorNoLoadState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.noSelfTestState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.compatibilityState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.powerKeyLongPressState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.forceDfuState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.deviceLockState = ByteUtil.bitValue(bytes[offset], 5, 1);
    output.cpuOverTempState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.imuOverTempState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;

    output.hwCompatibilityState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.fanLowSpeedState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.someBatteriesNotWorkState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.batteryNotCaliState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.chargeDangerWarningLevel = ByteUtil.bitValue(bytes[offset], 4, 2);
    output.chargeDangerWarningHandledState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.lockedBySafetyIssueState = ByteUtil.bitValue(bytes[offset], 7, 1);
  }

  @override
  int length() {
    return 8;
  }
}


class DefaultV6RealTimeErrorDelegate<T extends V6RealTimeError> extends _DefaultV6RealTimeErrorImpl<T> {}
